package com.app.common_app.service.impl;

import com.app.common_app.entity.User;
import com.app.common_app.mapper.UserMapper;
import com.app.common_app.service.UserService;
import com.app.public_dependency.exception.GlobalException;
import com.app.public_dependency.redis.RedisUtil;
import com.app.public_dependency.response.Result;
import com.app.public_dependency.token.TokenUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.cookie.DefaultCookie;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Service;
import reactor.netty.http.server.HttpServerResponse;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

/**
 * @author zhangzy
 * @description 针对表【user】的数据库操作Service实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
@DS("primary")
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    private final UserMapper userMapper;
    private final RedisTemplate<String, String> redisTemplate;

    /**
     * 用户 账号密码登录
     *
     * @param username  用户名
     * @param password  密码
     * @param autoLogin 是否自动登录
     * @param cookie    用户信息cookie
     * @param response  响应Http
     * @return 登录状态信息
     */
    @Override
    public Result accountLogin(String username, String password, Boolean autoLogin, String cookie, ServerHttpResponse response) {
        if (!"Null".equals(cookie)) {
            Claims claims = null;
            String phone = null;
            try {
                claims = TokenUtil.parsePayload(cookie);
                phone = (String) claims.get("username");
            } catch (ExpiredJwtException e) {
                log.error("登录失效");
                ResponseCookie newCookie = ResponseCookie.from("AuthorToken", null).maxAge(0).build();
                response.addCookie(newCookie);
                throw new ExpiredJwtException(null, null, null);
            }
            String secretKey = redisTemplate.opsForValue().get(claims.get("username") + "-AuthorToken");
            if (cookie.equals(secretKey)) {
                final Optional<User> user = userMapper.queryByPhone(phone);
                if (Optional.ofNullable(user).orElseThrow(() -> new GlobalException("用户不存在")).isPresent()) {
                    return Result.success().data("account", user);
                }
            }
        }
        Optional.ofNullable(username).orElseThrow(() -> new GlobalException("未填写用户名"));
        final Optional<User> user = userMapper.queryByPhoneAndPsw(username, password);
        if (Optional.ofNullable(user).orElseThrow(() -> new GlobalException("用户不存在")).isPresent()) {
            final String token = TokenUtil.genAccessToken(username);
            response.addCookie(ResponseCookie.from("AuthorToken", token).build());
            if (autoLogin) {
                redisTemplate.opsForValue().set(username + "-AuthorToken", token);
            }
            return Result.success().data("account", user);
        }
        return Result.error(500, "用户名或密码错误");
    }

    @Override
    public Result mobileLogin() {
        // TODO
        return null;
    }

    /**
     * 获取当前登录用户
     *
     * @param cookie cookie
     * @return 结果状态
     */
    @Override
    public Result fetchUserInfo(String cookie) {
        /*
         * 通过解析cookie中的数据，获取username，再去查数据库
         */
        final Claims claims = TokenUtil.parsePayload(cookie);
        final String phone = (String) claims.get("username");
        final Optional<User> user = userMapper.queryByPhone(phone);
        user.orElseThrow(() -> new GlobalException("用户数据发生变动"));
        return Result.success().data("currentUser", user).data("access", "admin");
    }

    /**
     * 账号登出
     *
     * @param response 响应Http
     * @return 结果状态
     */
    @Override
    public Result loginOut(String cookie, ServerHttpResponse response) {
        final Claims claims = TokenUtil.parsePayload(cookie);
        final String phone = (String) claims.get("username");
        ResponseCookie newCookie = ResponseCookie.from("AuthorToken", null).maxAge(0).build();
        response.addCookie(newCookie);
        redisTemplate.delete(phone + "-AuthorToken");
        return Result.success();
    }


}




